import Vue from "vue";

import VueRouter from "vue-router";

import store from "@/store";

//使用路由懒加载引入组件
const Home = () => import("@pages/Home");
const Search = () => import("@pages/Search");
const Login = () => import("@pages/Login");
const Register = () => import("@pages/Register");
const Detail = () => import("@pages/Detail");
const AddCartSuccess = () => import("@pages/AddCartSuccess");
const ShopCart = () => import("@pages/ShopCart");
const Pay = () => import("@pages/Pay");
const PaySuccess = () => import("@pages/PaySuccess");
const Trade = () => import("@pages/Trade");
const Center = () => import("@pages/Center");
const MyOrder = () => import("@pages/Center/MyOrder");
const TeamOrder = () => import("@pages/Center/TeamOrder");

Vue.use(VueRouter);

//重写路由器的push方法
// 1.先获取原始的push方法,供自定义push中使用
const lastPush = VueRouter.prototype.push;
/* 
  为什么要重写push,因为push方法返回promise实例,但是如果我们不传递第三个参数onAbort,则push内部的catch函数没有处理异常的回调函数,所以如果push出错,就会直接抛出错误到浏览器上
*/
//2.重写push,覆盖之前的push方法,但是我们的push方法默认传入了onComplate和onAbort参数的默认参数为一个函数,那么如果push出现问题后,就会有catch的函数帮我们处理异常了,这个就是重写push的核心
VueRouter.prototype.push = function (
  location,
  onComplete = () => {},
  onAbort = () => {}
) {
  /* 
    因为之前的push在VueRouter的原型对象上放,所以原本的push中this就是指向VueRouter的实例
    但是现在lastPush被直接默认调用,所以this就指向了undefined了,内部很可能出错
    我们在调用lastPush的时候,可以改变他的this指向VueRouter的实例
  */
  return lastPush.call(this, location, onComplete, onAbort);
};

const router = new VueRouter({
  scrollBehavior() {
    return {
      x: 0,
      y: 0,
    };
  },
  mode: "history",
  routes: [
    {
      path: "/home",
      component: Home,
      name: "home",
    },
    {
      path: "/search/:keyword?",
      component: Search,
      name: "search",
    },
    {
      path: "/login",
      component: Login,
      name: "login",
      meta: { footerIsHidden: true },

      /* //路由独享守卫控制login路由的权限
      beforeEnter(to, from, next) {
        //获取vuex中的token和用户名
        const token = store.state.user.token;
        if (token) {
          next("/");
        } else {
          next();
        }
      }, */
    },
    {
      path: "/register",
      component: Register,
      name: "register",
      meta: { footerIsHidden: true },
    },
    {
      path: "/detail/:skuId",
      component: Detail,
      name: "detail",
    },
    {
      path: "/addcartsuccess",
      component: AddCartSuccess,
      name: "addcartsuccess",

      //路由独享守卫,针对当前路由的跳转是否允许
      beforeEnter(to, from, next) {
        if (sessionStorage.getItem("cartData")) {
          next();
        } else {
          next("/shopcart");
        }
      },
    },
    {
      path: "/shopcart",
      component: ShopCart,
      name: "shopcart",
    },
    {
      path: "/pay",
      component: Pay,
      name: "pay",
      beforeEnter(to, from, next) {
        if (from.path.startsWith("/trade")) {
          next();
        } else {
          next("/shopcart");
        }
      },
    },
    {
      path: "/paysuccess",
      component: PaySuccess,
      name: "paysuccess",
      beforeEnter(to, from, next) {
        if (from.path.startsWith("/pay")) {
          next();
        } else {
          next("/shopcart");
        }
      },
    },
    {
      path: "/trade",
      component: Trade,
      name: "trade",
      beforeEnter(to, from, next) {
        if (from.path.startsWith("/shopcart")) {
          next();
        } else {
          next("/shopcart");
        }
      },
    },
    {
      path: "/center",
      component: Center,
      // name: "center",
      children: [
        {
          path: "myorder",
          component: MyOrder,
          name: "myorder",
        },
        {
          path: "teamorder",
          component: TeamOrder,
          name: "teamorder",
        },
        /* {
          path: "",
          component: MyOrder,
        }, */
        {
          path: "",
          redirect: "/center/myorder",
        },
      ],
    },
    {
      path: "/",
      redirect: "/home",
    },
  ],
});

/* 
  token校验逻辑:(目的:判断是否登录,并且登录后想要用户名)
    - 完成登录逻辑,拿到token,保存起来
    - 确定哪些页面需要token才能进入,哪些页面不需要token就可以进入
    - 因为每次进入路由前都要进行校验,所以我们选用全局前置守卫

    - 首先判断用户名是否存在,如果存在,则说明用户肯定是登录状态,并且我们也拥有的用户名,则直接放行

    - 在判断当前要去的路由是否是需要登录(token)的,然后再进行下一步操作
      - 如果当前的要去的路由地址不需要登录,则直接放行...
      - 如果当前的要去的路由地址需要登录,则检测是否拥有token
        - 如果拥有token,则获取一下用户名,并放行 
        - 如果没有token直接去登录页登陆以后,再来访问当前路由


*/

router.beforeEach(async (to, from, next) => {
  /* 
    to:要去的路由对象
    from:来源的路由对象
    next:决定下一步的操作
      - next():直接放行,去往to的路由地址
      - next("/login"):不再去往to的地址,而是去往next规定的地址
  */

  console.log(to, from);

  //使用一个数组,保存所有必须有token才能访问的路由地址
  const checkPath = ["/center", "/pay", "/paysuccess", "/trade"];

  //得到当前to的地址是否在checkPath中
  const isCheckPath = checkPath.some((item) => {
    //判断to.path 是否以 item为开头(考虑多级路由的请求)
    return to.path.startsWith(item);
  });

  //获取vuex中的token和用户名
  const token = store.state.user.token;
  const nickName = store.state.user.nickName;
  //1
  if (nickName) {
    return next();
  }

  //2
  if (isCheckPath) {
    //当前路径需要token校验
    //首先判断是否拥有token
    if (token) {
      console.log(1);
      //如果有token,则获取一下用户名,并放行
      try {
        //dispatch方法的返回值就是这个actions方法的返回值
        await store.dispatch("user/getUserName");
        next();
      } catch (e) {
        next("/login");
      }
    } else {
      //如果没有token则直接去登录页登录
      next("/login");
    }
  } else {
    //当前路由不需要token校验(但是如果此时你是有token的,我们可以顺便获取一下用户名) //如果有token,则获取一下用户名,并放行
    if (token) {
      try {
        //dispatch方法的返回值就是这个actions方法的返回值
        await store.dispatch("user/getUserName");
        next();
      } catch (e) {
        next("/login");
      }
    }

    next();
  }
});

export default router;
